package com.eonmind.user.provider;

import cn.hutool.json.JSONUtil;
import com.eonmind.common.contract.data.response.ResponseEntity;
import com.eonmind.common.contract.enums.user.NoticeTypeEnum;
import com.eonmind.common.contract.mail.iface.EmailService;
import com.eonmind.common.provider.entity.user.NotificationType;
import com.eonmind.common.provider.entity.user.User;
import com.eonmind.common.provider.entity.user.UserNotification;
import com.eonmind.common.provider.entity.user.UserNotificationPreference;
import com.eonmind.user.contract.api.UserNoticeFeignService;
import com.eonmind.user.contract.dto.UserNoticeDto;
import com.eonmind.user.converts.UserNoticeConvert;
import com.eonmind.user.mapper.NotificationTypeMapper;
import com.eonmind.user.mapper.UserMapper;
import com.eonmind.user.mapper.UserNotificationMapper;
import com.eonmind.user.mapper.UserNotificationPreferenceMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.RestController;

import java.text.MessageFormat;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.eonmind.common.provider.entity.user.UserNotificationPreference.NOTICE_TYPE_EMAIL;

/**
 * 用户通知服务Feign接口实现
 *
 * @author Xujie
 * @since 2025/6/1 16:24
 **/
@Slf4j
@RestController
public class UserNoticeFeignProvider implements UserNoticeFeignService {
    @Resource
    private UserMapper userMapper;
    @Resource
    private NotificationTypeMapper notificationTypeMapper;
    @Resource
    private UserNotificationPreferenceMapper userNotificationPreferenceMapper;
    @Resource
    private UserNotificationMapper userNotificationMapper;
    @Autowired
    private EmailService emailService;
    @Resource(name = "userDefaultTaskExecutor")
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    /**
     * 发送用户通知接口
     *
     * @param userSendNoticeRequest
     * @return
     */
    @Override
    public ResponseEntity<Void> sendUserNotice(UserNoticeDto.UserSendNoticeRequest userSendNoticeRequest) {
        Long userId = userSendNoticeRequest.getUserId();
        User user = userMapper.selectUserById(userId);
        if (ObjectUtils.isEmpty(user)) {
            log.error("用户通知发送失败，用户不存在：{}", JSONUtil.toJsonStr(userSendNoticeRequest));
            return ResponseEntity.message("用户通知发送失败，用户不存在");
        }
        List<NotificationType> notificationTypeList = notificationTypeMapper.selectAllValid();
        Map<Long, NotificationType> notificationTypeMap = notificationTypeList.stream()
                .collect(Collectors.toMap(NotificationType::getId, Function.identity()));
        List<UserNotificationPreference> userNotificationPreferences = userNotificationPreferenceMapper.selectByUserId(userId);
        if (ObjectUtils.isEmpty(userNotificationPreferences)) {
            log.info("用户通知发送失败，用户不存在通知配置：{}", JSONUtil.toJsonStr(userSendNoticeRequest));
            return ResponseEntity.message("用户通知发送失败，用户不存在通知配置");
        }
        for (UserNotificationPreference userNotificationPreference : userNotificationPreferences) {
            Long noticeTypeId = userNotificationPreference.getNoticeTypeId();
            if (ObjectUtils.compare(noticeTypeId, userSendNoticeRequest.getNoticeType().getCode()) != 0) {
                continue;
            }
            NotificationType notificationType = notificationTypeMap.get(noticeTypeId);
            if (ObjectUtils.isEmpty(notificationType)) {
                log.info("用户通知发送跳过，系统不存在这条通知类型：{}", JSONUtil.toJsonStr(userNotificationPreference));
                continue;
            }
            List<NotificationType.NoticeTemplate> noticeTemplates = notificationType.getNoticeTemplates();
            Map<Integer, NotificationType.NoticeTemplate> noticeTemplateMap = noticeTemplates.stream()
                    .collect(Collectors.toMap(NotificationType.NoticeTemplate::getType, Function.identity()));
            threadPoolTaskExecutor.execute(() -> {
                // 首先添加站内通知
                sendNoticeToInSite(userSendNoticeRequest, noticeTemplateMap.get(NoticeTypeEnum.IN_SITE.getCode()));
                // 添加邮件通知
                if (userNotificationPreference.isNoticeEnabled(NOTICE_TYPE_EMAIL)) {
                    sendNoticeToEmail(user, userSendNoticeRequest, noticeTemplateMap.get(NoticeTypeEnum.EMAIL.getCode()));
                }
            });
        }
        return ResponseEntity.success();
    }

    protected void sendNoticeToEmail(User user, UserNoticeDto.UserSendNoticeRequest userSendNoticeRequest, NotificationType.NoticeTemplate noticeTemplate) {
        if (ObjectUtils.isEmpty(noticeTemplate)) {
            log.error("对应的邮件通知模板未配置，发送失败：{}", JSONUtil.toJsonStr(userSendNoticeRequest));
            return;
        }
        String noticeContent = noticeTemplate.getNoticeContent();
        String formattedContent = String.format(noticeContent, user.getUserName(), userSendNoticeRequest.getNoticeContent());
        UserNotification userNotification = new UserNotification();
        userNotification.setNoticeNotifyType(NoticeTypeEnum.EMAIL.getCode());
        userNotification.setUserId(userSendNoticeRequest.getUserId());
        userNotification.setNoticeTypeId(userSendNoticeRequest.getNoticeType().getCode());
        userNotification.setNoticeTitle(userSendNoticeRequest.getNoticeTitle());
        userNotification.setNoticeContent(formattedContent);
        userNotification.setNoticeTags(UserNoticeConvert.toUserNoticeTagDataList(userSendNoticeRequest.getNoticeTags()));
        userNotificationMapper.save(userNotification);

        // 发送邮件
        String email = user.getEmail();
        if (ObjectUtils.isEmpty(email)) {
            log.error("用户通知发送失败，用户不存在邮箱：{}", JSONUtil.toJsonStr(userSendNoticeRequest));
            return;
        }
        emailService.sendHtmlMessage(email, userSendNoticeRequest.getNoticeTitle(), formattedContent);
    }

    protected void sendNoticeToInSite(UserNoticeDto.UserSendNoticeRequest userSendNoticeRequest, NotificationType.NoticeTemplate noticeTemplate) {
        if (ObjectUtils.isEmpty(noticeTemplate)) {
            log.error("对应的站内通知模板未配置，发送失败：{}", JSONUtil.toJsonStr(userSendNoticeRequest));
            return;
        }
        String noticeContent = noticeTemplate.getNoticeContent();
        String formattedContent = MessageFormat.format(noticeContent, userSendNoticeRequest.getNoticeContent());
        UserNotification userNotification = new UserNotification();
        userNotification.setUserId(userSendNoticeRequest.getUserId());
        userNotification.setNoticeTypeId(userSendNoticeRequest.getNoticeType().getCode());
        userNotification.setNoticeTitle(userSendNoticeRequest.getNoticeTitle());
        userNotification.setNoticeContent(formattedContent);
        userNotification.setNoticeTags(UserNoticeConvert.toUserNoticeTagDataList(userSendNoticeRequest.getNoticeTags()));
        userNotificationMapper.save(userNotification);
    }

}
